(function($) {
  $.fn.jquests = function(options) {
    // Build main options before element iteration.
    var opts = $.extend({}, $.fn.jquests.defaults, options);

    var jquests = $(this);
    jquests.opts = opts;
    jquests.rules = opts.rules;
    jquests.addClass('jquests-list ui-widget ui-widget-content ui-corner-all');

    jquests.prerender_ = function() {
      $(jquests)
                .css('position', 'fixed')
                .css('width', 300)
                .css('z-index', 10000);

      $(jquests).position({
        my: 'center top',
        at: 'center top+20',
        of: window
      });

      $(jquests).draggable({ cursor: 'move', containment: 'window' });
    };

    jquests.init_ = function() {
      jquests.hide();

      jquests.children().each(function() {
        var $this = $(this);
        opts.quests.push($this);
        $this.hide();
      });

      opts.quests[opts.currentQuest].show();
      jquests.append('<div class="jquests-tip"/>');
      jquests.prerender_();

      jquests.show('drop', {direction: 'up'}, 300);
    };

    jquests.questDone = function(idx) {
      if (opts.currentQuest != idx ||
          opts.currentQuest == opts.quests.length - 1)
        return;

      opts.quests[opts.currentQuest].hide();
      jquests.setTip('');

      opts.currentQuest++;
      opts.quests[opts.currentQuest].show();
      jquests.effect('highlight');

      opts.onAfterQuestDone.call(jquests);

      if (opts.currentQuest == opts.quests.length - 1)
        opts.onAfterAllDone.call(jquests);
    };

    jquests.questReject = function(msg) {
      jquests.setTip(msg);
      jquests.effect('shake');
    };

    jquests.setTip = function(msg) {
      jquests.children('.jquests-tip').text(msg);
    };

    jquests.init_();
    return jquests;
  };

  $.fn.jquests.defaults = {
    currentQuest: 0,
    quests: [],
    rules: [],
    onAfterQuestDone: function() { },
    onAfterAllDone: function() { }
  };
})(jQuery);
